package com.xtayfjpk.zookeeper.test;

import java.util.Arrays;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.AsyncCallback.StatCallback;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class DataMonitor implements Watcher, StatCallback {
	ZooKeeper zk;
	String znode;
	Watcher chainedWatcher;
	boolean dead;
	DataMonitorListener listener;
	byte[] prevData;

	public DataMonitor(ZooKeeper zk, String znode, Watcher chainedWatcher,
            DataMonitorListener listener) {
		this.zk = zk;
		this.znode = znode;
		this.chainedWatcher = chainedWatcher;
		this.listener = listener;
		
		zk.exists(znode, true, this, null);
	}
	
	@Override
	public void process(WatchedEvent event) {
		String path = event.getPath();
		if(event.getType()==EventType.None) {
			if(event.getState()==Watcher.Event.KeeperState.SyncConnected) {
				
			} else if(event.getState()==Watcher.Event.KeeperState.Expired) {
				dead = true;
				listener.closing(KeeperException.Code.SESSIONEXPIRED.intValue());
			}
		} else {
			if(path!=null && path.equals(znode)) {
				zk.exists(znode, true, this, null);
			}
		}

		if(chainedWatcher!=null) {
			chainedWatcher.process(event);
		}
	}

	@SuppressWarnings("deprecation")
	@Override
	public void processResult(int rc, String path, Object ctx, Stat stat) {
		boolean exists;
		switch(rc) {
			case Code.Ok :
				exists = true;break;
			case Code.NoNode :
				exists = false;break;
			case Code.SessionExpired :
			case Code.NoAuth:
				dead = true;
				listener.closing(rc);
				return;
			default:
				zk.exists(znode, true, this, null);
				return;
		}
		
		byte[] b = null;
		if(exists) {
			try {
				b = zk.getData(znode, false, null);
			} catch (KeeperException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		if((b==null && b!=prevData) || (b!=null && !Arrays.equals(prevData,  b))) {
			listener.exists(b);
			prevData = b;
		}
		
	}

}
